from django.http import JsonResponse
import random
from rest_framework.views import APIView
from . import models
from ApiTest import models as api_models
from WEBTest import models as web_models
from django.contrib.contenttypes.models import ContentType
from . import serializers
from utils.models_choices import ModelsChoices
from utils.get_query_params import GetQueryParams
from utils.commonviews import CommonAPIView
from rest_framework.response import Response
from ProjectTool.common_tool.db_tool.db_conf import DB_TYPES
from ProjectTool.common_tool.data_tool.file_uploaded import FileUploaded
from ProjectTool.SqlTool.sql_data import SqlData
from ProjectTool.common_tool.data_tool.get_query_dict import GetQueryDict
from ProjectTool.common_tool.data_tool.save_sql_detail import SaveSqlDetail
from ProjectTool.common_tool.in_out_parameter import InParameter,StepsData
from utils.base_response import BaseResponse
from django.http.request import QueryDict
from django.core.files.uploadedfile import InMemoryUploadedFile
from ProjectTool.CasesTool.execute_cases_tool import ExecuteCasesTool


# Create your views here.
# 获取choices数据
def get_choices(request):
    MODELS_CHOICES = ModelsChoices().get_models_choices()
    return JsonResponse(MODELS_CHOICES)


# 测试sql语句
class TestSql(APIView):
    def get(self, request):
        res = BaseResponse()
        queryset = models.SqlDetail.objects.filter(id=request.GET.get('id')).first()
        ser_obj = SqlData(queryset)
        db_class = DB_TYPES.get(ser_obj.db_type)
        # 数据库连接
        database_info = ser_obj.db_info
        db_obj = db_class(**database_info)
        # 实例化入参类
        in_out_obj = InParameter(ser_obj.sql_push_fields, ser_obj.sql_template)
        in_out_obj.run()
        sql_data = in_out_obj.sql_data
        if in_out_obj.res.status:
            return Response(in_out_obj.res.dict)
        # 执行处理后的sql
        data = db_obj.execute_select(sql_data)
        # 关闭数据库连接
        db_obj.close()
        if db_obj.res.status:
            return Response(db_obj.res.dict)
        # 实例化出参类
        out_obj = StepsData(ser_obj.sql_pull_fields, data,None)
        out_obj.run()
        if out_obj.res.status:
            return Response(out_obj.res.dict)
        # 文件实例化处理
        sql_test_data_obj = FileUploaded(out_obj.out_data, 'sql_test_data.txt').get_uploaded_file()
        # 实例化QueryDict对象
        qq = GetQueryDict().get_query()
        qq.__setitem__('sql_test_data', sql_test_data_obj)
        qq.__setitem__('sql_data', sql_data)
        # 序列化后保存
        save_obj = SaveSqlDetail(serializers.SqlDetailSerializers, ser_obj.queryset, qq)
        save_obj.save()
        # if save_obj.res.status:
        #     return Response(save_obj.res.dict)
        return Response(save_obj.res.dict)


# 常用工具
class OftenMyToolModelViewSet(CommonAPIView):
    query_set = models.OftenMyTool.objects.all().order_by('id')
    serializer_class = serializers.OftenMyToolSerializers
    input_get_list = [('often_my_tool_id', 'id'),
                      ('inputObjName', 'title__contains')]
    input_put_list = [('often_my_tool_id', 'id')]
    input_delete_list = [('often_my_tool_id', 'id')]
    input_dict = GetQueryParams


# 附件列表接口
class AttachmentModelViewSet(CommonAPIView):
    query_set = models.Attachment.objects.all().order_by('id')
    serializer_class = serializers.AttachmentSerializers
    input_get_list = [('attachment_id', 'id'),
                      ('file_format', 'file_format'),
                      # ('file_size', 'file_size'),
                      ('inputObjName', 'file_name__contains')]
    input_put_list = [('attachment_id', 'id')]
    input_delete_list = [('attachment_id', 'id')]
    input_dict = GetQueryParams


# 数据库接口
class DatabaseModelViewSet(CommonAPIView):
    query_set = models.Database.objects.all().order_by('id')
    serializer_class = serializers.DatabaseSerializers
    input_get_list = [('database_id', 'id'), ('database_name', 'db_name__contains'),
                      ('inputObjName', 'db_name__contains')]
    input_put_list = [('database_id', 'id')]
    input_delete_list = [('database_id', 'id')]
    input_dict = GetQueryParams


# 环境接口
class EnvironmentModelViewSet(CommonAPIView):
    query_set = models.Environment.objects.all().order_by('id')
    serializer_class = serializers.EnvironmentSerializers
    input_get_list = [('environment_id', 'id'), ('environment_name', 'env_title__contains'),
                      ('inputObjName', 'env_title__contains')]
    input_put_list = [('environment_id', 'id')]
    input_delete_list = [('environment_id', 'id')]
    input_dict = GetQueryParams


# SQL接口
class SqlDetailModelViewSet(CommonAPIView):
    query_set = models.SqlDetail.objects.all().order_by('id')
    serializer_class = serializers.SqlDetailSerializers
    input_get_list = [('sqldetail_id', 'id'), ('sqldetail_name', 'sql_title__contains'),
                      ('inputObjName', 'sql_title__contains')]
    input_put_list = [('sqldetail_id', 'id')]
    input_delete_list = [('sqldetail_id', 'id')]
    input_dict = GetQueryParams

    def post(self, request):
        fields = ['sql_data_str']
        data = request.data
        if isinstance(data, QueryDict):
            _mutable = data._mutable
            data._mutable = True
            for key in data:
                if key in fields and not isinstance(data[key], InMemoryUploadedFile):
                    obj = FileUploaded(data[key], ''.join([key, '.txt'])).get_uploaded_file()
                    data[key] = obj
            data._mutable = _mutable
        return self.create(request)

    def put(self, request):
        fields = ['sql_data_str']
        data = request.data
        if isinstance(data, QueryDict):
            _mutable = data._mutable
            data._mutable = True
            for key in data:
                if key in fields and not isinstance(data[key], InMemoryUploadedFile):
                    obj = FileUploaded(data[key], ''.join([key, '.txt'])).get_uploaded_file()
                    data[key] = obj
            data._mutable = _mutable
        return self.update(request)


# 项目接口
class ProjectModelViewSet(CommonAPIView):
    query_set = models.Project.objects.all().order_by('id')
    serializer_class = serializers.ProjectSerializers
    input_get_list = [('project_id', 'id'), ('project_name', 'name__contains'), ('inputObjName', 'name__contains')]
    input_put_list = [('project_id', 'id')]
    input_delete_list = [('project_id', 'id')]
    input_dict = GetQueryParams


# 模块接口
class ModuleModelViewSet(CommonAPIView):
    query_set = models.Module.objects.all().order_by('id')
    serializer_class = serializers.ModuleSerializers
    input_get_list = [('module_id', 'id'),
                      ('module_project', 'project'),
                      ('module_name', 'name__contains'),
                      ('inputObjName', 'name__contains')
                      ]
    input_put_list = [('module_id', 'id')]
    input_delete_list = [('module_id', 'id')]
    input_dict = GetQueryParams


# 用例接口
class CasesModelViewSet(CommonAPIView):
    query_set = models.Cases.objects.all().order_by('id')
    serializer_class = serializers.CasesSerializers
    input_get_list = [('cases_id', 'id'),
                      ('cases_project', 'project'),
                      ('cases_module', 'module'),
                      ('cases_test_person', 'test_person'),
                      ('cases_status', 'status'),
                      ('cases_property', 'property'),
                      ('cases_test_status', 'test_status'),
                      ('cases_name', 'name__contains'),
                      ('inputObjName', 'name__contains')
                      ]
    input_put_list = [('cases_id', 'id')]
    input_delete_list = [('cases_id', 'id')]
    input_dict = GetQueryParams


# 用例测试
class TestCases(APIView):
    def post(self, request):
        res = BaseResponse()
        cases_ids = request.data.get('id')
        if cases_ids:
            cases_exe_obj = ExecuteCasesTool(cases_ids)
            res.data = cases_exe_obj.run()
            res.msg = '''
            执行完成！
            共{cases_sum}条用例，
            执行用例{cases_execute_sum}条，
            失败用例{cases_failure_sum}条,
            未执行用例{cases_not_execute_sum}条,
            失败用例id列表：{cases_failure_ids}，
            共{cases_detail_sum}条明细，
            执行明细{cases_detail_execute_sum}条，
            失败明细{cases_detail_failure_sum}条,
            未执行明细{cases_detail_not_execute_sum}条,
            失败明细id列表：{cases_detail_failure_ids}。
            '''.format(cases_sum=res.data.get('cases_sum'),
                       cases_execute_sum=res.data.get('cases_execute_sum'),
                       cases_failure_sum=res.data.get('cases_failure_sum'),
                       cases_not_execute_sum=res.data.get('cases_not_execute_sum'),
                       cases_failure_ids=res.data.get('cases_failure_ids'),
                       cases_detail_sum=res.data.get('cases_detail_sum'),
                       cases_detail_execute_sum=res.data.get('cases_detail_execute_sum'),
                       cases_detail_failure_sum=res.data.get('cases_detail_failure_sum'),
                       cases_detail_not_execute_sum=res.data.get('cases_detail_not_execute_sum'),
                       cases_detail_failure_ids=res.data.get('cases_detail_failure_ids'),
                       )
        else:
            res.status = 1
            res.msg = '无用例id，请确认后再进行测试！'
        return Response(res.dict)


# 用例步骤接口
class CasesDetailModelViewSet(CommonAPIView):
    query_set = models.CasesDetail.objects.all().order_by('cases_id', 'sort')
    serializer_class = serializers.CasesDetailSerializers
    input_get_list = [('cases_detail_id', 'id'),
                      ('cases_id', 'cases'),
                      ('cases_detail_status', 'status'),
                      ('cases_detail_test_status', 'test_status'),
                      ('cases_detail_name', 'title__contains'),
                      ('inputObjName', 'title__contains')
                      ]
    input_put_list = [('cases_detail_id', 'id')]
    input_delete_list = [('cases_detail_id', 'id')]
    input_dict = GetQueryParams


# 获取随机字符串
class RandomString(APIView):
    def post(self, request):
        res = BaseResponse()
        try:
            res_data = request.data
            str_len = res_data.get('str_len')
            str_list = []
            for j in range(str_len):
                chr_index = random.randint(65, 90) + random.randint(0, 1) * 32
                str_list.append(chr(chr_index))
            res.data = ''.join(str_list)
        except Exception as e:
            res.status = 1
            res.msg = '获取随机字符串失败！'
            res.error = str(e.args)
        return Response(res.dict)


# 获取表对象
class ContentTypeModelViewSet(CommonAPIView):
    query_set = ContentType.objects.all().order_by('id')
    serializer_class = serializers.ContentTypeSerializers
    input_get_list = [('content_type_id', 'id'),
                      ('inputObjName', 'title__contains')
                      ]
    input_put_list = [('content_type_id', 'id')]
    input_delete_list = [('content_type_id', 'id')]
    input_dict = GetQueryParams
    # 需要关联的表数据
    read_class = [
        api_models.ApiDetail,  # 接口明细表类
        web_models.Steps,  # web步骤表
    ]

    def get(self, request):
        contents = []
        for content in self.query_set:
            model_class = content.model_class()
            if model_class in self.read_class:
                contents.append(content.id)
        # self.query_set = ContentType.objects.filter(id__in=contents)
        self.query_set = self.query_set.filter(id__in=contents)
        return self.list(request)


# 获取表数据url
class ContentTypeObject(APIView):
    def get(self, request):
        res = BaseResponse()
        content_type_id = request.GET.get('id')
        content = ContentType.objects.filter(id=content_type_id)
        # 用于获取用例步骤对象的列表
        urls = [
            (api_models.ApiDetail, 'api/apiDetail/'),  # 接口明细表
            (web_models.Steps, 'web/Steps/'),  # web步骤表
        ]
        if content.count():
            content = content.first()
            model_class = content.model_class()
            for url in urls:
                if model_class == url[0]:
                    res.data = url[1]
                    res.msg = '操作成功！'
                    break
            else:
                if not res.data:
                    res.status = 1
                    res.msg = '获取失败,该模块不在测试步骤之内！'
        else:
            if not res.data:
                res.status = 1
                res.msg = 'ContentType对象获取失败！'
        return Response(res.dict)
